﻿using FreeDream.Entity;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations.Schema;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Text;
using System.Threading.Tasks;

namespace FreeDream.DBUtility
{
    public class BloggingContext : DbContext
    {
        #region 部分说明

        //管理数据库架构的 EnsureCreated()
        //EnsureDeleted 方法将删除数据库（如果存在）。 如果没有适当的权限，则会引发异常。
        //// Drop the database if it exists
        //dbContext.Database.EnsureDeleted();
        //EnsureCreated 将创建数据库（如果不存在）并初始化数据库架构。 如果存在任何表(包含另一个 DbContext 类的) ，则架构不会初始化。
        //// Create the database if it doesn't exist
        //dbContext.Database.EnsureCreated();
        //若要获取SQL，EnsureCreated可以使用 GenerateCreateScript 方法。
        //var sql = dbContext.Database.GenerateCreateScript();

        #endregion

        ////Microsoft.Extensions.Logging.Console
        //private static readonly ILoggerFactory _loggerFactory = LoggerFactory.Create(builder => builder.AddConsole());

        public BloggingContext()
        {
        }

        public BloggingContext(DbContextOptions<BloggingContext> options)
            : base(options)
        {
        }

        public DbSet<Blog> Blogs { get; set; }
        public DbSet<BlogPost> Posts { get; set; }

        public DbSet<Student> Student { get; set; }


        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {
            if (!optionsBuilder.IsConfigured)
            {
                optionsBuilder.UseSqlServer(@"Server=.;Database=EFCoreCodeFirst;uid=sa;pwd=123");
            }
            ////optionsBuilder.UseSqlServer(@"Server=(localdb)\mssqllocaldb;Database=Blogging;Trusted_Connection=True");
            ////延迟加载实现包--Microsoft.EntityFrameworkCore.Proxies
            ////optionsBuilder.UseLazyLoadingProxies(false);
            ///
            //optionsBuilder.UseSqlServer(ConnectionString, p => p.CommandTimeout(GlobalContext.SystemConfig.DBCommandTimeout));
            ////optionsBuilder.AddInterceptors(new DbCommandCustomInterceptor());
            //optionsBuilder.UseLoggerFactory(_loggerFactory);
            //// 这里需要注意，不能采用这种写法：optionsBuilder.UseLoggerFactory(LoggerFactory.Create(builder => builder.AddConsole()));
            //// 会导致内存泄露的问题
        }

        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            #region 部分使用说明

            ////如果不希望在模型中包含某一类型，则可以排除它
            //modelBuilder.Ignore<Blog>();
            ////从迁移中排除表的功能。
            //modelBuilder.Entity<Blog>().ToTable("AspNetUsers", t => t.ExcludeFromMigrations());
            ////配置实体
            //new BlogEntityTypeConfiguration().Configure(modelBuilder.Entity<Blog>());
            ////配置要在特定架构中创建的表
            //modelBuilder.Entity<Blog>().ToTable("blogs", schema: "blogging");
            ////在模型级别使用 Fluent API 定义默认架构，而不是为每个表指定架构：
            //modelBuilder.HasDefaultSchema("blogging");

            ////EF 假定数据库中已存在引用的视图，它不会在迁移中自动创建它。
            //modelBuilder.Entity<Blog>().ToView("blogsView", schema: "blogging");
            ////对数据库表设置任意文本注释，从而在数据库中记录架构
            //modelBuilder.Entity<Blog>().HasComment("Blogs managed on the website");
            ////在使用共享类型实体类型时必须提供该名称。 这意味着，必须使用 Set 调用来实现对应的 DbSet 属性。
            //modelBuilder.SharedTypeEntity<Dictionary<string, object>>(
            //"Blog", bb =>
            //{
            //    bb.Property<int>("BlogId");
            //    bb.Property<string>("Url");
            //    bb.Property<DateTime>("LastUpdated");
            //});

            #endregion

            modelBuilder.Entity<Blog>().HasComment("Blog表");
            modelBuilder.Entity<Blog>().HasKey(e => e.BlogId).HasName("PK_BlogId");
            modelBuilder.Entity<Blog>().Property(e => e.BlogId).IsRequired();

            modelBuilder.Entity<BlogPost>().HasKey(e => e.BlogId);
            modelBuilder.Entity<BlogPost>().Property(e => e.PostId).IsRequired();

            base.OnModelCreating(modelBuilder);
        }

    }


    /// <summary>
    /// 为了减小 OnModelCreating 方法的大小，可以将实体类型的所有配置提取到实现 IEntityTypeConfiguration<TEntity> 的单独类中
    /// 然后，只需从 OnModelCreating 调用 Configure 方法。
    /// </summary>
    public class BlogEntityTypeConfiguration : IEntityTypeConfiguration<Blog>
    {
        public void Configure(EntityTypeBuilder<Blog> builder)
        {
            builder.Property(b => b.Url).IsRequired();
        }
    }

    #region 实体

    //public class Blog
    //{
    //    public string BlogId { get; set; }
    //    public string Url { get; set; }
    //    public string Title { get; set; }
    //    public int Rating { get; set; }
    //    public DateTime CreateDateTime { get; set; }
    //    public string Description { get; set; }


    //    //public List<BlogPost> Posts { get; set; }
    //}

    //public class BlogPost
    //{
    //    public string PostId { get; set; }
    //    public string Title { get; set; }
    //    public string Content { get; set; }

    //    public DateTime CreateDateTime { get; set; }

    //    public string BlogId { get; set; }
    //    //public Blog Blog { get; set; }
    //}

    //public class Student
    //{
    //    public string Id { get; set; }

    //    public string Code { get; set; }

    //    public string Name { get; set; }
    //}

    #endregion
}
